


import ListEventHooksHandler from './1.0';

import {
  constructorOptions,
  subClassLoaderOptions,
  HookOption,
  Actions,
  cancelParameter,
} from '../typings'




export default class SubHandler_v_1_1 extends  ListEventHooksHandler {
  // 版本日志
  // 版本日志
  public static versionLogs = {
    zh: {
      hooks: `
/**
 * 版本 1.1 更新日志 (2019/10/31)
 * 1. 新增 handler.cancel 函数, 可对未触发的异步 (Promise) 进行阻断
 * 2. 新增 自动清洗异步队列等相关阻断补充
 */\n`,
      fields : ``,
      template: ListEventHooksHandler.versionLogs.zh.template
    },
    en: {

    }
  }

  // 执行包
  protected execPackaging({eventOption,action,vm,event,result,eventFuncString,scription}) {
    // 如果是异步, 将记录队列, 并注入拦截, 用于判断是否阻断后续执行
    if ( /return\s+(new\s+Promise\(|Promise\.all)|Promise\.race\(/.test(eventFuncString) ) {
      // 将事件塞入队列
      let eventQueueItem = { key:SubHandler_v_1_1.generateEventKey(event,action), finished:false, canceled:false };
      this.eventQueue.push(eventQueueItem);
      eventFuncString = eventFuncString.replace(/\.\s*then\s*\(/, `.then(resp=>{
        var eventQueueItem = handler.eventQueue.filter(e=>e.key==='${eventQueueItem.key}')[0];
        if ( !eventQueueItem ) return resp;
        else {
          eventQueueItem.finished = true;
          handler.clearEventQueue();
          if ( eventQueueItem.canceled ) return new Promise(function(){});
          else return resp;
        }
      }).then(`);
    }

    return new Promise((resolve,reject)=>{
      let args = eventOption.isActionEvent? [action]: [];
      try {
        args = args.concat((eventOption.params).map(paramItem=>(
          paramItem==='$vm'? vm: this.parseParams(paramItem))
        ));
        // actionDone 会额外注入 result 参数
        if ( event==='onActionDone' ) { args.push(result) }
        // 执行
        resolve(
          eval(
            `(function(vm,opts,handler) {
              return (${eventFuncString}).call(opts, ...args)
            })`
          )(this.vm, scription, this)
        );
      }
      // 异常处理, 加文字标识, 以便定位问题
      catch(err) {
        reject(`ListEventHooksHandler Execution <${event}> Error => ( ${err.toString()} )`);
      }
    });
  }

  /**
   * DELAY:TODO: 取消异步执行
   * @param params 因为存在多种取消情况, 所以做整合传值
   * @returns status:string = success | done, fail 的情况只有抛异常
   */
  protected eventQueue:any[] = [];               // 事件队列
  cancel(params:cancelParameter) {
    let { event,action,positive=false,cancelAll=false } = params;
    let keyPrefix = '';

    // 如果传了event
    if ( event ) {
      if (!this.hooksOption.find(o=>o.name===event)) throw `ListEventHooksHandler Error: Hook "${event}" not found!`
      keyPrefix += `${event}_`;
    }

    // 如果传了action
    if ( action ) {
      // 没有 actionCode
      if ( !action.actionCode ) throw `ListEventHooksHandler Error: Invalid action parameter!`;
      // 没有/找不到依赖的事件
      if ( !event ) throw `ListEventHooksHandler Error: Actions base on event, but event not found!`;
      if ( !this.hooksOption.find(o=>o.name===event) )
        throw `ListEventHooksHandler Error: Actions base on event, but event "${event}" not found`;

      // 字段头
      keyPrefix += `${action.actionCode}_`;
    }

    // 如果队列是空的, 直接返回成功
    if ( !this.eventQueue.length ) return true;


    // NOTE: 至此, keyPrefix 仍然可能等于空'', 那它将无差别进行匹配


    // 设定遍历方向, 默认反向
    let traverStart=this.eventQueue.length-1,traverEnd=-1, traverStep=-1;
    if ( positive ) {
      traverStart = 0;
      traverEnd = this.eventQueue.length;
      traverStep = 1;
    }

    // 对复合条件的队列项打标记
    for ( let traverItem; traverStart!==traverEnd; traverStart+=traverStep ) {
      traverItem = this.eventQueue[traverStart];
      if ( !traverItem.canceled && traverItem.key.startsWith(keyPrefix) ) {
        traverItem.canceled = true;
        // 是否取消全部
        if ( !cancelAll ) break;
      }
    }


    return true;
  }


  /**
   * 销毁, 预留
   */
  destroy() {
    // 执行队列清理
    this.cancel({cancelAll:true});
    this.clearEventQueue();
  }


    /**
   * 自动清理队列
   */
  protected clearEventQueueTimer;
  protected clearEventQueueDelay = 5000;
  protected clearEventQueue() {
    clearTimeout( this.clearEventQueueTimer );
    this.clearEventQueueTimer = setTimeout(() => {
      // 去掉完成, 保留未完成(包括已取消但未完成)
      this.eventQueue = this.eventQueue.filter(e=>!e.finished);
    }, this.clearEventQueueDelay);
  }

  /**
   * 生成事件队列item
   * key生成规则: 时间毫秒数+同一毫秒数的次数计算, 作为字符串拼接, 不会对后面的时间戳造成影响
   */
  private static previousEventKey:string = '';
  private static eventKeyGeneratationCounting:number = 0;
  static generateEventKey(event,action) {
    let eventKey = '';
    if ( event ) eventKey += `${event}_`;
    if ( action && action.actionCode ) eventKey += `${action.actionCode}_`;
    eventKey += Date.now();

    if ( eventKey===this.previousEventKey ) {
      eventKey += ++this.eventKeyGeneratationCounting;
    } else {
      this.eventKeyGeneratationCounting = 0;
    }
    this.previousEventKey = eventKey;
    return eventKey;
  }


  // 校验
  // isScripStringValid(str:any) {
  //   return true;
  // }
  // private isScriptObjectAvailabile(obj:any):boolean {
  //   return true;
  // }
}